type UploadConfig = {
  headers?: Record<string, string>;
  onSliceProgress?: (progress: number) => void;
};

/**
 * 使用 XHR 上传切片
 * @param formData - 包含文件切片数据的 FormData
 * @param uploadUrl - 上传接口的 URL
 * @param config - 可选配置项 (headers, onSliceProgress)
 */
function uploadFile(formData: FormData, uploadUrl: string, config?: UploadConfig): Promise<void> {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("POST", uploadUrl, true);

    // 设置自定义请求头
    if (config?.headers) {
      for (const [key, value] of Object.entries(config.headers)) {
        xhr.setRequestHeader(key, value);
      }
    }

    // 监听切片上传进度
    xhr.upload.onprogress = (event) => {
      if (config?.onSliceProgress && event.lengthComputable) {
        const progress = (event.loaded / event.total) * 100;
        config.onSliceProgress(progress); // 切片上传进度
      }
    };

    xhr.onload = () => {
      if (xhr.status === 200) {
        resolve(); // 上传成功
      } else {
        reject(new Error(`上传失败，状态码：${xhr.status}`)); // 上传失败
      }
    };

    xhr.onerror = () => reject(new Error("上传出错"));
    xhr.send(formData);
  });
}

/**
 * 上传文件并支持断点续传
 * @param file - 要上传的文件对象
 * @param sliceSize - 每片的大小（字节数）
 * @param uploadUrl - 上传接口的 URL
 * @param onProgress - 整体上传进度回调
 * @param config - 可选配置项
 */
export async function uploadSlice(
  file: File,
  sliceSize: number,
  uploadUrl: string,
  onProgress?: (progress: number) => void,
  config?: UploadConfig,
) {
  const totalSlices = Math.ceil(file.size / sliceSize); // 总片数
  const fileId = file.name + "-" + file.size; // 文件唯一标识
  let failedSlices: number[] = []; // 存储失败的切片
  const localStorageKey = `uploaded-slices-${fileId}`; // 本地存储 key

  // 加载已上传的切片
  const savedSlices = localStorage.getItem(localStorageKey);
  const uploadedSlices = new Set<number>(savedSlices ? JSON.parse(savedSlices) : []);

  // 上传每个切片
  for (let index = 0; index < totalSlices; index++) {
    if (uploadedSlices.has(index)) {
      continue; // 跳过已上传的切片
    }

    // 创建切片
    const start = index * sliceSize;
    const end = Math.min(start + sliceSize, file.size);
    const slice = file.slice(start, end);

    // 上传切片
    const formData = new FormData();
    formData.append("file", slice);
    formData.append("fileId", fileId); // 文件唯一 ID
    formData.append("index", index.toString()); // 切片索引
    formData.append("totalSlices", totalSlices.toString()); // 总切片数

    try {
      await uploadFile(formData, uploadUrl, config);
      uploadedSlices.add(index); // 上传成功，添加到已上传切片集合

      // 更新进度
      if (onProgress) {
        onProgress(Math.floor((uploadedSlices.size / totalSlices) * 100));
      }
    } catch (error) {
      console.error(`切片 ${index} 上传失败`, error);
      failedSlices.push(index); // 上传失败，记录失败切片
    }
  }

  // 将已上传的切片记录到本地存储
  localStorage.setItem(localStorageKey, JSON.stringify(Array.from(uploadedSlices)));

  // 返回上传结果
  if (failedSlices.length > 0) {
    return { finish: false, uploadedSlices: Array.from(uploadedSlices), failedSlices };
  } else {
    // 清除本地存储中的已上传切片数据
    localStorage.removeItem(localStorageKey);
    return { finish: true, uploadedSlices: Array.from(uploadedSlices), failedSlices };
  }
}
